package com.shelpe.services.algorithm.entity.jpa;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

import javax.persistence.AttributeConverter;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;

import com.shelpe.services.algorithm.entity.jpa.DevelopmentKeyword.DevelopmentKeywordPK;
import com.shelpe.services.algorithm.entity.jpa.DevelopmentPlan.PremiumType;
import com.shelpe.services.algorithm.entity.jpa.DevelopmentPlan.PremiumTypeConverter;

import lombok.Data;

@Entity(name = "development_keyword")
@IdClass(DevelopmentKeywordPK.class)
@Data
public class DevelopmentKeyword {
	@Id
	@Column(name="plan_id")
	private long planID;
	@Id
	@Column(name="keyword_id")
	private long keywordID;
	
	private String word;
	
	private int target;
	@Convert(converter=TargetTypeConverter.class)
	private TargetType targetType;
	
	@Convert(converter=StatusConverter.class)
	private Status status;
	@Column(name="original")
	private int originalValue;
	
	private Date createdTime;
	private Date modifiedTime;
	@Column(name="lastest")
	private int lastRank;
	
	private int maxPrice;
	@Convert(converter=PremiumTypeConverter.class)
	private PremiumType premiumType;
	private BigDecimal premium;
	
	
	public boolean isByMatch(){
		return this.getTargetType() == DevelopmentKeyword.TargetType.preciseMatch || this.getTargetType() == DevelopmentKeyword.TargetType.wideMatch;
	}
	
	public boolean isByPricing(){
		return !this.isByMatch();
	}
	
	public int calcTargetUpperRank(){
		return Math.max(1, this.target - this.targetType.value);
	}
	
	public static enum TargetType{
		fixed(1), range3(3),range4(4), range10(10), range20(20), preciseMatch(-1), wideMatch(-4), qscore(-2);
		private int value;

		private TargetType(int v) {
			this.value = v;
		}

		public int getValue() {
			return this.value;
		}
		
		public static TargetType from(int v){
			TargetType status = TargetType.fixed;
			for (TargetType s : TargetType.values()) {
				if (s.getValue() == v) {
					status = s;
					break;
				}
			}
			return status;
		}
	}
	
	public static enum Status{
		executable(0), locked(1), negative(2), overflowed(3);
		private int value;

		private Status(int v) {
			this.value = v;
		}

		public int getValue() {
			return this.value;
		}
		
		public static Status from(int v){
			Status status = Status.executable;
			for (Status s : Status.values()) {
				if (s.getValue() == v) {
					status = s;
					break;
				}
			}
			return status;
		}
	}
	
	public static class StatusConverter implements AttributeConverter<Status, Integer> {

		@Override
		public Integer convertToDatabaseColumn(Status attribute) {
			return attribute != null ? attribute.getValue() : Status.executable.getValue();
		}

		@Override
		public Status convertToEntityAttribute(Integer dbData) {
			return Status.from(dbData);
		}
	}
	
	public static class TargetTypeConverter implements AttributeConverter<TargetType, Integer> {

		@Override
		public Integer convertToDatabaseColumn(TargetType attribute) {
			return attribute != null ? attribute.getValue() : TargetType.fixed.value;
		}

		@Override
		public TargetType convertToEntityAttribute(Integer dbData) {
			return TargetType.from(dbData);
		}
	}
	
	@Data
	public static class DevelopmentKeywordPK implements Serializable{
		private static final long serialVersionUID = 1L;
		@Column(name="plan_id")
		private long planID;
		@Column(name="keyword_id")
		private long keywordID;
		
		public DevelopmentKeywordPK(){}
		public DevelopmentKeywordPK(long tID, long kID){
			this.planID = tID;
			this.keywordID = kID;
		}
	}
}
